<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    class SnapshotSandbox {
      constructor() {
        this.proxy = window;
        this.modifyPropsMap = {}; // 修改了那些属性
        this.active();
      }
      active() {
        this.windowSnapshot = {}; // window对象的快照
        for (const prop in window) {
          if (window.hasOwnProperty(prop)) {
            // 将window上的属性进行拍照
            this.windowSnapshot[prop] = window[prop];
          }
        }
        Object.keys(this.modifyPropsMap).forEach(p => {
          window[p] = this.modifyPropsMap[p];
        });
      }
      inactive() {
        for (const prop in window) { // diff 差异
          if (window.hasOwnProperty(prop)) {
            // 将上次拍照的结果和本次window属性做对比
            if (window[prop] !== this.windowSnapshot[prop]) {
              // 保存修改后的结果
              this.modifyPropsMap[prop] = window[prop];
              // 还原window
              window[prop] = this.windowSnapshot[prop];
            }
          }
        }
      }
    }
    // 快照沙箱
    let sandbox = new SnapshotSandbox();
      ((window) => {
      window.a = 1;
      window.b = 2;
      window.c = 3
      console.log(a,b,c)
      sandbox.inactive();
      console.log(a,b,c)
    })(sandbox.proxy);
    /* 
      局限：如果有多个子应用，就不能使用这种方式了
      proxy代理沙箱，可以实现多应用沙箱，把不同的应用用不同的代理处理
     */
  </script>

  <script>
    // proxy 代理沙箱
    class ProxySandbox {
      constructor() {
        const rawWindow = window;
        const fakeWindow = {}
        const proxy = new Proxy(fakeWindow, {
          set(target, p, value) {
            target[p] = value;
            return true
          },
          get(target, p) {
            return target[p] || rawWindow[p];
          }
        });
        this.proxy = proxy
      }
    }
    let sandbox1 = new ProxySandbox();
    let sandbox2 = new ProxySandbox();
    window.a = 1;

    ((window) => {
      window.a = 'hello';
      console.log(window.a)
    })(sandbox1.proxy);

    ((window) => {
      window.a = 'world';
      console.log(window.a)
    })(sandbox2.proxy);
  </script>
</body>
</html>